package core.models;

import java.io.IOException;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.DefaultListModel;

import net.SSHConnection;
import net.SSHConnectionProxy;

public class RuleSet extends DefaultListModel {
	/**
	 * 
	 */
	private static final long serialVersionUID = -4608876116647811108L;
	private List<Rule> ruleSet;
	private List<Rule> flushRuleSet;
	private List<Rule> policyRuleSet;

	public RuleSet() {
		ruleSet = new AbstractList<Rule>() {
			@Override
			public int size() {
				return getSize();
			}

			@Override
			public Rule get(int index) {
				return (Rule) elementAt(index);
			}
		};

		policyRuleSet = new ArrayList<Rule>(3);
		flushRuleSet  = new ArrayList<Rule>(2);
	}

	public void loadRemoteRules(String table) throws IOException {
		SSHConnection conn = new SSHConnectionProxy();
		this.clearRuleSets();
		List<String> rulesList = conn.getRules(table);
		Pattern p = Pattern.compile("( -m \\w+)|((!)? -[a-ln-z])");
		String[] ruleElements;
		Rule newRule = null;
		for (String rule : rulesList) {
			ruleElements = rule.split(" ");
			if (ruleElements[0].equals("-P")) {
				PolicyRule newPolicyRule = new PolicyRule(table, ruleElements[1],
						ruleElements[2]);
				policyRuleSet.add(newPolicyRule);
			} else {
				if (table.equals("filter"))
				newRule = new FilterRule(ruleElements[0],
						ruleElements[1]);
				else if (table.equals("nat"))
					newRule = new NatRule(ruleElements[0], ruleElements[1]);
				Matcher m1 = p.matcher(rule);
				int start = 0;
				while (m1.find(start)) {
					Matcher m2 = p.matcher(rule);
					int optionEnd;
					if (m2.find(m1.end()))
						optionEnd = m2.start();
					else
						optionEnd = -1;
					newRule.addOption(m1.group().trim(),
							optionEnd == -1 ? rule.substring(m1.end() + 1)
									: rule.substring(m1.end() + 1, optionEnd));
					start = m1.end();
				}
				addElement(newRule);
			}
		}
	}

	public void sendRules(String table) throws IOException {
		SSHConnection conn = new SSHConnectionProxy();
		// Flush rules
		for (Rule r : flushRuleSet) {
			conn.sendRule(r);
		}
		
		// Policy rules
		for (Rule r : policyRuleSet) {
			conn.sendRule(r);
		}
		
		// Rules
		for (Rule r : ruleSet) {
			conn.sendRule(r);
		}
		
		// Reload rules
		this.loadRemoteRules(table);
	}

	public List<Rule> getRuleSet() {
		return ruleSet;
	}

	public List<Rule> getPolicyRuleSet() {
		return policyRuleSet;
	}
	
	public List<Rule> getFlushRuleSet() {
		return flushRuleSet;
	}
	
	public void setPolicyRuleSet(List<Rule> policies) {
		this.policyRuleSet = policies;
	}
	
	private void clearRuleSets() {
		flushRuleSet.clear();
		policyRuleSet.clear();
		clear();
	}
}
